﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Services;
using MainGame.GamePlay;

namespace MainGame.Menu
{

  public interface ILevelRecapScreen
  {
    event MenuEvent PlayAgain;
    event MenuEvent BackToMain;
  }

  /// <summary>
  /// Mostriamo lo score di fine livello
  /// </summary>
  public class LevelRecapScreen : BaseMenu, ILevelRecapScreen
  {
    Button NewGameBtn, BackToMainBtn;
    Texture2D white_pixel, box;
    float ScaleFactor = 15f;
    SpriteFont largeFont, baveuse;
    Rectangle resultsRect;
    Vector2 infoPosition;
    
    // Moltiplicatore difficolta', moltiplicatori prime sei carte, bonus mazzetto + grande
    float difficultyFactor;
    string difficultyString;
    int[] cardFactors, cardTotals;
    public int[] mazzetti;
    int cardsNumber, bonusMazzetto, totalScore;
    float elapsedTime;
    TimeSpan gameCompletionTime;
    Color difficultyColor, boxColor;
    static readonly int CARD_WIDTH = 110;
    static readonly float DRAW_INTERVAL = 0.2f;


     public LevelRecapScreen(Game game, MenuDepths depth)
      : base(game, depth)
    {
      background = null; // game.Content.Load<Texture2D>(@"Images\\Menu\\SquarePaper");
      bounds = game.GraphicsDevice.Viewport.Bounds;
      // bounds = new Rectangle(0, 0, 825, 1408);
      game.Services.AddService(typeof(ILevelRecapScreen), this);
    }

     protected override void Dispose(bool disposing)
     {
       Game.Services.RemoveService(typeof(ILevelRecapScreen));
       base.Dispose(disposing);
     }

    public override void Initialize()
    {
      //var board_renderer = Game.Services.GetService(typeof(BoardRenderer)) as BoardRenderer;
      //mazzetti = board_renderer.mazzetto;
      var viewportBounds = Game.GraphicsDevice.Viewport.Bounds;
      resultsRect = new Rectangle(0, viewportBounds.Center.Y - 70, viewportBounds.Width, viewportBounds.Height / 2);

      elapsedTime = 0.0f;

      var board_service = Game.Services.GetService(typeof(IBoardState)) as IBoardState;
      totalScore = board_service.Players.ElementAt(0).Score;

      var ui_renderer = Game.Services.GetService(typeof(IUIRenderer)) as UIRenderer;
      gameCompletionTime = TimeSpan.FromSeconds((double)ui_renderer.elapsedTime);

      // Calcola moltiplicatori prime 6 posizioni in base alla difficolta'
      GameDifficulty difficulty = Game.GetContext().currentConfig.difficulty;
      // Cambia colori e scritte in base alla difficolta'
      if (difficulty == GameDifficulty.Easy)
      {
        difficultyColor = Color.Green;
        boxColor = Color.Lerp(Color.PaleGreen, Color.Transparent, 0.3f);
        difficultyString = Locale.Strings.DifficultyEasy;
      }
      else if (difficulty == GameDifficulty.Normal)
      {
        difficultyColor = new Color(238, 190, 0);
        boxColor = Color.Lerp(new Color(255, 249, 143), Color.Transparent, 0.3f);
        difficultyString = Locale.Strings.DifficultyMedium;
      }
      else
      {
        difficultyColor = new Color(225, 0, 0);
        boxColor = Color.Lerp(new Color(255, 122, 122, 150), Color.Transparent, 0.3f);
        difficultyString = Locale.Strings.DifficultyHard;
      }
      // Calcola il fattore difficolta'
      difficultyFactor = 1.0f + ((int)difficulty * 1.0f);   // Easy = 1, Normal = 2, Hard = 3
      cardsNumber = Math.Min(6, board_service.Players.ElementAt(0).Cards.Count()); // Considera solo le carte entro le prime sei posizioni
      cardFactors = new int[cardsNumber];
      cardTotals = new int[cardsNumber];
      var board_renderer = Game.Services.GetService(typeof(IBoardRenderer)) as BoardRenderer;
      mazzetti = board_renderer.mazzetto.Take(cardsNumber).ToArray();
      for (int i = 0; i < cardsNumber; ++i)
      {
        // Easy: 5 5 4 3 2 1
        // Normal: 10 10 8 6 4 2
        // Hard: 15 15 12 9 6 3
        cardFactors[i] = (int)((6 - i) * difficultyFactor);
        if (i == 0)
          --cardFactors[i];
        cardTotals[i] = cardFactors[i] * mazzetti[i];
      }

      // Calcola bonus mazzetto piu' grande
      bonusMazzetto = 0;
      for (int i = 0; i < cardsNumber; ++i)
        bonusMazzetto = Math.Max(bonusMazzetto, mazzetti[i]);
      
      //// Calcola punteggio totale
      //for (int i = 0; i < cardsNumber; ++i)
      //  totalScore += cardFactors[i] * mazzetti[i];
      //totalScore += (int)(bonusMazzetto * difficultyFactor);

      // Posizione informazioni
      infoPosition = new Vector2(resultsRect.Location.X + 10 + (cardsNumber * CARD_WIDTH), resultsRect.Location.Y + 28);

      largeFont = Game.Content.Load<SpriteFont>("large_font");
      baveuse = Game.Content.Load<SpriteFont>("baveuse1_font");
      white_pixel = Game.Content.Load<Texture2D>("white_pixel");
      box = Game.Content.Load<Texture2D>(@"Images//Menu//HelpBg2");

      NewGameBtn = new Button(Game, @"Images//Menu//button2", new Rectangle(viewportBounds.Width - 250, 400, 200, 60), Color.Red, "baveuse1_font", Locale.Strings.NewGame.Replace("\\n", " "), Color.White, 0.6f);
      AddButton(NewGameBtn, () =>
      {
        if (PlayAgain != null)
          PlayAgain();
      });

      BackToMainBtn = new Button(Game, @"Images//Menu//button2", new Rectangle(40, 400, 230, 60), Color.Blue, "baveuse1_font", Locale.Strings.BackToMain.Replace("\\n", " "), Color.White, 0.6f);
      AddButton(BackToMainBtn, () =>
      {
        if (BackToMain != null)
          BackToMain();
      });

      base.Initialize();
    }

    SpriteBatch spriteBatch;
    //SpriteFont large_font;
    Matrix screen_transform;
    protected override void LoadContent()
    {
      var content = Game.Content;

      spriteBatch = Game.GetContext().SpriteBatch;
      screen_transform = Game.GetContext().ScreenTransform;

      base.LoadContent();
    }

    public override void Update(GameTime gameTime)
    {
      // Input: back button pressed
      if (((Game1)Game).IsBackButtonPressed())
      {
        if (BackToMain != null)
          BackToMain();
      }

      elapsedTime += gameTime.dt();
      
      base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
      base.Draw(gameTime);

      spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, screen_transform);

      // Draw temporizzate di punteggi
      //if (elapsedTime > 3)
      //{
      //  spriteBatch.DrawString(baveuse, Game.GetContext().currentConfig.difficulty.ToString(), infoPosition, difficultyColor, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
      //  for (int i = 0; i < cardsNumber; ++i)
      //  {
      //    // Seconda riga: "<fattore posizione>"
      //    spriteBatch.DrawString(baveuse, cardFactors[i].ToString(), new Vector2(resultsRect.Location.X + 50 + (CARD_WIDTH * i), resultsRect.Location.Y), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
      //  }
      //}

      for (int i = 0; i < cardsNumber; ++i)
      {
        float largestString = Math.Max(baveuse.MeasureString(mazzetti[i].ToString()).X, baveuse.MeasureString(cardFactors[i].ToString()).X);
        // Draw dei punteggi parziali in base alla posizione
        if (elapsedTime > 2 + (DRAW_INTERVAL * i))
        {
          // Prima riga: "<numero carte nel mazzetto>"
          spriteBatch.DrawString(baveuse, mazzetti[i].ToString(), new Vector2(resultsRect.Location.X + 85 + (CARD_WIDTH * i), resultsRect.Location.Y), Color.Green, 0.0f, new Vector2(baveuse.MeasureString(mazzetti[i].ToString()).X, 0), 0.8f, SpriteEffects.None, 0.0f);
          //spriteBatch.DrawString(baveuse, Locale.Strings.CardsStacked, new Vector2(infoPosition.X, infoPosition.Y + 25), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 1.0f);          
        }

        // Draw dei fattori posizione
        if (elapsedTime > (2.5 + (DRAW_INTERVAL * cardsNumber)))
        {
          spriteBatch.DrawString(baveuse, difficultyString, infoPosition, difficultyColor, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 0.0f);
          spriteBatch.DrawString(baveuse, "*", new Vector2(resultsRect.Location.X + 87 + (CARD_WIDTH * i), resultsRect.Location.Y), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 0.0f);
          // Seconda riga: "<fattore posizione> ="
          spriteBatch.DrawString(baveuse, cardFactors[i].ToString(), new Vector2(resultsRect.Location.X + 85 + (CARD_WIDTH * i), resultsRect.Location.Y + 25), Color.Green, 0.0f, new Vector2(baveuse.MeasureString(cardFactors[i].ToString()).X, 0), 0.8f, SpriteEffects.None, 0.0f);
          spriteBatch.DrawString(baveuse, "=", new Vector2(resultsRect.Location.X + 92 + (CARD_WIDTH * i), resultsRect.Location.Y + 25), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 0.0f);
        }

        // Draw dei punteggi posizione parziali
        if (elapsedTime > (3.2 + (DRAW_INTERVAL * cardsNumber)))
        {
          // Terza riga: "---"
          spriteBatch.Draw(white_pixel, new Rectangle(resultsRect.Location.X + 25 + (CARD_WIDTH * i), resultsRect.Location.Y + 60, 75, 5), Color.Green);
          // Quarta riga: "<totale posizione>"
          spriteBatch.DrawString(baveuse, cardTotals[i].ToString(), new Vector2(resultsRect.Location.X + 85 + (CARD_WIDTH * i), resultsRect.Location.Y + 55), Color.Green, 0.0f, new Vector2(baveuse.MeasureString(cardTotals[i].ToString()).X, 0), 0.8f, SpriteEffects.None, 1.0f);
          //spriteBatch.DrawString(baveuse, Locale.Strings.PositionTotal, new Vector2(infoPosition.X, infoPosition.Y + 55), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
        }
      }

      // Draw di una box sotto i moltiplicatori di posizione
      if (elapsedTime > (2.5 + (DRAW_INTERVAL * cardsNumber)))
      {
        spriteBatch.Draw(white_pixel, new Rectangle(0, resultsRect.Location.Y + 35, Game.GraphicsDevice.Viewport.Width, 25), null, boxColor, 0.0f, Vector2.Zero, SpriteEffects.None, 0.5f);
      }

      // Draw del bonus mazzetto
      if (elapsedTime > (4 + (DRAW_INTERVAL * cardsNumber)))
      {
        spriteBatch.DrawString(baveuse, "+", new Vector2(resultsRect.Location.X + 30, resultsRect.Location.Y + 95), Color.Green, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
        spriteBatch.DrawString(baveuse, Locale.Strings.StackBonus, new Vector2(resultsRect.Location.X + 50, resultsRect.Location.Y + 100), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 0.0f);
        spriteBatch.DrawString(baveuse, bonusMazzetto.ToString(), new Vector2(resultsRect.Location.X + 60 + (baveuse.MeasureString(Locale.Strings.StackBonus).X * 0.8f), resultsRect.Location.Y + 100), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 0.0f);
      }

      // Draw del punteggio totale
      if (elapsedTime > (5 + (DRAW_INTERVAL * cardsNumber)))
      {
        spriteBatch.DrawString(baveuse, Locale.Strings.TotalScore, new Vector2(resultsRect.Location.X + 50, resultsRect.Location.Y + 160), Color.Red);
        spriteBatch.DrawString(baveuse, totalScore.ToString(), new Vector2(resultsRect.Location.X + 60 + baveuse.MeasureString(Locale.Strings.TotalScore).X, resultsRect.Location.Y + 135), Color.Red, 0, Vector2.Zero, ScaleFactor, SpriteEffects.None, 0);
        if (ScaleFactor > 2)
          ScaleFactor -= 0.7f;
      }

      // Draw del tempo di gioco
      //if (elapsedTime > (5.5 + (DRAW_INTERVAL * cardsNumber)))
      //{
      //  spriteBatch.DrawString(baveuse, Locale.Strings.Time + ":", new Vector2(resultsRect.Location.X + 560, resultsRect.Location.Y + 110), Color.Green, 0, Vector2.Zero, 0.7f, SpriteEffects.None, 0);
      //  spriteBatch.DrawString(baveuse, String.Format("{0:mm}:{1:ss}", gameCompletionTime, gameCompletionTime), new Vector2(resultsRect.Location.X + 660, resultsRect.Location.Y + 105), Color.Green, 0, Vector2.Zero, 0.9f, SpriteEffects.None, 0);
      //}

      //// Draw dei punteggi parziali in base alla posizione
      //for (int i = 0; i < cardsNumber; ++i)
      //{
      //  if (elapsedTime > 3 + (DRAW_INTERVAL * i))
      //  {
      //    float largestString = Math.Max(baveuse.MeasureString(mazzetti[i].ToString()).X, baveuse.MeasureString(cardFactors[i].ToString()).X);
      //    // Prima riga: "<numero carte nel mazzetto> *"
      //    spriteBatch.DrawString(baveuse, mazzetti[i].ToString(), new Vector2(resultsRect.Location.X + 50 + (CARD_WIDTH * i), resultsRect.Location.Y), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
      //    spriteBatch.DrawString(baveuse, "*", new Vector2(resultsRect.Location.X + 50 + (CARD_WIDTH * i) + largestString, resultsRect.Location.Y), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 1.0f);
      //    // Seconda riga: "<fattore posizione> ="
      //    spriteBatch.DrawString(baveuse, "=", new Vector2(resultsRect.Location.X + 50 + (CARD_WIDTH * i) + largestString, resultsRect.Location.Y + 25), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 1.0f);
      //    //spriteBatch.DrawString(baveuse, Locale.Strings.CardsStacked, new Vector2(infoPosition.X, infoPosition.Y + 25), Color.Green, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 1.0f);          
      //    // Terza riga: "---"
      //    spriteBatch.Draw(white_pixel, new Rectangle(resultsRect.Location.X + 35 + (CARD_WIDTH * i), resultsRect.Location.Y + 60, 60, 5), Color.Green);
      //    // Quarta riga: "<totale posizione>"
      //    spriteBatch.DrawString(baveuse, cardTotals[i].ToString(), new Vector2(resultsRect.Location.X + 50 + (CARD_WIDTH * i), resultsRect.Location.Y + 55), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
      //    //spriteBatch.DrawString(baveuse, Locale.Strings.PositionTotal, new Vector2(infoPosition.X, infoPosition.Y + 55), Color.Green, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);
      //  }

      //  // Draw del punteggio totale
      //  if (elapsedTime > (4 + (DRAW_INTERVAL * cardsNumber)))
      //  {
      //    spriteBatch.DrawString(baveuse, Locale.Strings.TotalScore, new Vector2(resultsRect.Location.X + 50, resultsRect.Location.Y + 105), Color.Red);
      //    spriteBatch.DrawString(baveuse, totalScore.ToString(), new Vector2(resultsRect.Location.X + 450, resultsRect.Location.Y + 80), Color.Red, 0, Vector2.Zero, ScaleFactor, SpriteEffects.None, 0);
      //    if (ScaleFactor > 2)
      //      ScaleFactor -= 0.1f;
      //  }
      //}

      spriteBatch.End();
    }

    public event MenuEvent PlayAgain;
    public event MenuEvent BackToMain;
  }
}
